﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using K9Nano.IM.Models;
using K9Nano.LayIM;
using K9Nano.LayIM.Models;
using K9Nano.LayIM.Stores;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using WalkingTec.Mvvm.Core;

namespace K9Nano.IM.LayIM
{
    public class ChatRoomStore : ChatStoreBase, IChatRoomStore
    {
        public ChatRoomStore(IDataContext db, IOptions<LayIMOptions> options) : base(db, options)
        {
        }

        public async Task<LayIMChatRoom> GetAsync(string appId, string customerId, CancellationToken cancellation)
        {
            Guid.TryParse(customerId, out var customerGId);
            Guid.TryParse(appId, out var appGId);

            var app = await Db.Set<ChatApp>().FirstOrDefaultAsync(x => x.ID == appGId, cancellation);

            if (app == null) throw new Exception($"App {appId} not found");

            var room = await Db.Set<ChatRoom>().FirstOrDefaultAsync(x => x.CustomerId == customerGId
                                                                          && x.AppId == app.ID, cancellation);

            var customer = await Db.Set<User>().FirstOrDefaultAsync(x => x.ID == customerGId, cancellation);
            if (customer == null)
            {
                throw new Exception($"User {customerId} not found");
            }

            if (room == null)
            {
                room = new ChatRoom
                {
                    AppId = app.ID,
                    CustomerId = customerGId,
                    Name = $"【{app.Name}】{customer.Nickname ?? customer.Name}",
                    Members = new List<ChatRoomMember>
                    {
                        new ChatRoomMember
                        {
                            MemberId = customerGId
                        }
                    }
                };
                await Db.Set<ChatRoom>().AddAsync(room, cancellation);
                
                try
                {
                    await Db.SaveChangesAsync(cancellation);
                }
                catch (Exception ex) when (ex.Message.Contains("idx_customer_app"))
                {
                    room = await Db.Set<ChatRoom>().FirstAsync(x => x.CustomerId == customerGId
                                                                              && x.AppId == app.ID, cancellation);
                }
            }

            return new LayIMChatRoom
            {
                Id = room.ID.ToString(),
                Title = app.Name + " 在线客服",
                Avatar = GetAvatar(customer),
                App = appId,
                Name = room.Name
            };
        }

        public async Task AddMemberAsync(string roomId, string memberId, CancellationToken cancellation)
        {
            Guid.TryParse(roomId, out var roomGid);
            Guid.TryParse(memberId, out var memberGid);

            var any = await Db.Set<ChatRoomMember>()
                .AnyAsync(x => x.RoomId == roomGid && x.MemberId == memberGid, cancellation);

            if (any)
            {
                return;
            }

            var member = new ChatRoomMember
            {
                RoomId = roomGid,
                MemberId = memberGid
            };

            Db.AddEntity(member);

            await Db.SaveChangesAsync(cancellation);
        }
    }
}